import random
import re
from datetime import datetime
from flask import request, abort, jsonify, make_response, json, session
from info import redis_store, db
from info.constants import IMAGE_CODE_REDIS_EXPIRES
from info.models import User
from info.utils.captcha.captcha import captcha
from info.modules.passport import login_blu
from info.utils.response_code import RET
from info.utils.yuntongxun.sms import CCP


@login_blu.route('/image_code', methods=['get', 'post'])
def get_image():
    # 1.获取url中的验证码id
    image_code_id = request.args.get('imageCodeId', None)
    # 2.判断是否有值
    if not image_code_id:
        abort(403)
    # 3.生成验证图片
    name, text, image = captcha.generate_captcha()
    # 4.保存到redis里
    try:
        redis_store.set('image_code' + image_code_id, text, IMAGE_CODE_REDIS_EXPIRES)
    except Exception as f:
        print(f)
        return '图片有误'
    # 5.返回图片验证码给浏览器(返回的是text格式， 改为image/jpg格式)
    response = make_response(image)
    response.headers['Content-Type'] = 'image/jpg'
    return response


@login_blu.route('sms_code', methods=['post','get'])
def send_sms_code():
    """
    接收前端发送过来的请求参数
    检查参数是否已经全部传过来
    判断手机号格式是否正确
    检查图片验证码是否正确，若不正确，则返回
    删除图片验证码
    生成随机的短信验证码
    使用第三方SDK发送短信验证码
    :return:
    """
    # 1.接受参数（手机号, 用户id, 用户输入的验证码）
    params_dict = json.loads(request.data)
    # params_modile = params_dict.get('mobile')
    # params_image_code = params_dict.get('image_code')
    # params_image_code_id = params_dict.get('image_code_id')
    params_modile = params_dict['mobile']
    params_image_code = params_dict['image_code']
    params_image_code_id = params_dict['image_code_id']

    # 2.判断接受参数是否正确
    if not all([params_modile, params_image_code, params_image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg= '参数错误')
    # 3.判断手机号是否有误
    if not re.match(r'1[35678]\d{9}', params_modile):
        return jsonify(errno=RET.PARAMERR, errmsf='手机格式有误')
    # 4.取出redis中的图片验证码
    try:
        real_image_code = redis_store.get('image_code' + params_image_code_id)
    except Exception as f:
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
    # 5.判断redis中real_image_code是否有值，image_code_id有过期时间
    if not real_image_code:
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
    # 6.判断验证码是否一致(转换成小写，用户输入可能为有大写也有小写)
    if params_image_code.lower() != real_image_code.lower():
        return jsonify(erron=RET.DATAERR, errmsg='输入验证码有误')
    # 7.生成6位数的随机数字
    random_num = "%06d" % random.randint(0, 9999)
    print(random_num)
    ccp = CCP()
    send_sms = ccp.send_template_sms(params_modile, [random_num, 5], 1)
    if send_sms != 0:
        return jsonify(errno=RET.THIRDERR, errmsg='第三方系统错误')
    # 8.将手机号保存到redis中
    try:
        redis_store.set('sms' + params_modile, random_num, IMAGE_CODE_REDIS_EXPIRES)
    except Exception as f:
        print(f)
        return jsonify(errno=RET.PARAMERR, errmsg='保存手机号错误')
    return jsonify(errno=RET.OK, errmsg='发送成功')


@login_blu.route('/register', methods=['post'])
def register():
    """
    1.接受参数（手机号, 用户输入验证码, 密码）
    2.判断是否都有值
    3.取出redis中的手机号和验证码
    4.对比用户输入的手机号和验证码 是否一致
    5.若一致则保存用户到Users数据库中
    6.返回响应给浏览器
    :return:
    """
    # 1.接受参数
    json_data = json.loads(request.data)
    modile = json_data.get('mobile')
    smscode = json_data.get('smscode')
    password = json_data.get('password')
    # 2.判断是否有值
    if not all([modile, smscode, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
    # 3.取出redis中的验证码
    try:
        real_msm_code = redis_store.get('sms'+ modile)
    except Exception as f:
        return jsonify(errno=RET.DBERR, errmsg="获取本地验证码失败")
    # 查看验证码是否过期
    if not real_msm_code:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码过期")
    # 4.对比用户输入的手机号和验证码 是否一致
    if smscode.lower() != real_msm_code.lower():
        return jsonify(errno=RET.DATAERR, errmsg="短信验证码错误")
    # 5.若一致则保存用户到Users数据库中
    # 初始化User模型,并添加到数据库中
    user = User()
    user.mobile = modile
    user.nick_name = modile
    # 将密码加密保存在加入数据库中
    user.password = password
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as f:
        print(f)
        db.session.rollback()
        return jsonify(errno=RET.DATAERR, errmsg="数据保存错误")
    # 6.保存用户状态
    session['user_id'] = user.id
    session['modile'] = user.mobile
    session['nick_name'] = user.nick_name
    #7.返回响应给浏览器
    return jsonify(errno=RET.OK, errmsg='注册成功')


@login_blu.route('/login', methods=['post'])
def login():
    """
    1.接受参数(用户名,密码)
    2.校验参数(是否为空)
    3.判断是否注册过(数据库有没有这个用户)
    4.判断用户名及密码是否正确
    5.保存用户登录状态
    6.返回响应
    :return:
    """
    # 1.接受参数
    params_dict = request.json
    password = params_dict.get('password')
    mobile = params_dict.get('mobile')
    # 2.校验参数,及手机号码格式是否正确
    if not all([password, mobile]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
    if not re.match(r'1[35678]\d{9}', mobile):
        return jsonify(errno=RET.ROLEERR,errmsg='手机输入有误')
    # 3.判断这个用户是否注册过(判断数据库是否有这个用户)
    user =None
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as f:
        print(f)
        return jsonify(errno=RET.DBERR, errmsg="查询数据错误")
    if not user:
        return jsonify(errno=RET.USERERR, errmsg="用户不存在")
    # 4.判断用户名及密码是否正确
    if not user.check_passowrd(password):
        return jsonify(errno=RET.PWDERR, errmsg="密码错误")
    # 5.保存用户状态
    session['user_id'] = user.id
    session['modile'] = user.mobile
    session['nick_name'] = user.nick_name
    # 记录用户最后一次登录时间,保存到数据库中
    user.last_login = datetime.now()
    try:
        db.session.commit()
    except Exception as f:
        print(f)
        db.session.rollback()
        # 不用return 保证用户登录成功
        # return jsonify(errno=RET.DATAERR, errmsg="数据保存错误")
    # 6.返回响应
    return jsonify(errno=RET.OK, errmsg='登录成功')


@login_blu.route('/logout')
def logout():
    session.pop('user_id', None)
    session.pop('modile', None)
    session.pop('nick_name', None)
    session.pop('is_admin', None)
    return jsonify(errno=RET.OK, errmsg='退出成功')




